package com.eastfair.venuebooking.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.eastfair.venuebooking.dao.ContactMapper;
import com.eastfair.venuebooking.dao.ContractManageMapper;
import com.eastfair.venuebooking.dao.CustomerMainMapper;
import com.eastfair.venuebooking.dto.*;
import com.eastfair.venuebooking.entity.*;
import com.eastfair.venuebooking.enumeration.BelongRecordOperateTypeEnum;
import com.eastfair.venuebooking.enums.CustomerStateEnum;
import com.eastfair.venuebooking.enums.VenueBookingMoudleEnum;
import com.eastfair.venuebooking.exceptioncode.VenueBookingExceptionCode;
import com.eastfair.venuebooking.service.*;
import com.eastfair.venuebooking.vo.ContractHistogramVO;
import com.eastfair.venuebooking.vo.ContractManageVO;
import com.eastfair.venuebooking.vo.CustomerMainVO;
import com.eastfair.venuebooking.vo.CustomerStatisticsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 客户表
 * </p>
 *
 * @author linan
 * @date 2022 -06-08
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class CustomerMainServiceImpl extends SuperServiceImpl<CustomerMainMapper, CustomerMain> implements CustomerMainService {

    @Resource
    private ContactService contactService;

    @Resource
    private BelongRecordService belongRecordService;

    @Resource
    private UserCustomerStarService userCustomerStarService;

    @Resource
    private ContactRefService contactRefService;

    @Resource
    private ExhibitionService exhibitionService;

    @Resource
    private BusinessOpportunityService businessOpportunityService;

    @Resource
    private FollowRecordService followRecordService;

    @Resource
    private SaleClueService saleClueService;

    @Resource
    private ContractManageService contractManageService;

    @Resource
    private CustomerMainMapper customerMainMapper;

    @Resource
    private ContractManageMapper contractManageMapper;

    @Resource
    private ContactMapper contactMapper;

    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<CustomerMain> modelList) {
        modelList
                .forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(CustomerMain model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public IPage<CustomerMainVO> listCustomerMainVOs(PageParams<CustomerMainQuery> pageParam) {
        log.info("listCustomerMainVOs - 查询客户列表, pageParam={}", pageParam);

        handlerQueryParams(pageParam);
        IPage<CustomerMain> page = pageParam.buildPage();
        QueryWrapper<CustomerMain> queryWrapper = createCustomerMainQueryWrapper(pageParam.getModel());
        IPage<CustomerMainVO> voPage = customerMainMapper.listCustomerMains(page, queryWrapper);

        List<CustomerMainVO> customerMainVOList = voPage.getRecords();
        customerMainVOList
                .forEach(customerMainVO -> {
                    customerMainVO.setContactMobile(TypeHandlerUtil.decrypt(customerMainVO.getContactMobile()));
                    // 计算未跟进天数
                    if (customerMainVO.getLastFollowDate() != null) {
                        int notFollowDays
                                = (int) LocalDateTimeUtil.between(customerMainVO.getLastFollowDate(), LocalDateTime.now(), ChronoUnit.DAYS);
                        notFollowDays = Math.max(notFollowDays, 0);
                        customerMainVO.setNotFollowDays(notFollowDays);
                    }
                });
        return voPage;
    }

    @Override
    public List<CustomerMainVO> listWaitCmsSync() {
        log.info("listByCmsSync - 查询待同步到cms的客户");
        QueryWrapper<CustomerMain> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(CustomerMain::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(CustomerMain::getCmsSync, BusinessConstant.NO)
                .orderByAsc(CustomerMain::getUpdateTime)
                .last("limit 100")
        ;
        List<CustomerMain> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(customerMain -> BeanUtil.toBean(customerMain, CustomerMainVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public CustomerMainVO getCustomerMainVOById(Long id) {
        log.info("getCustomerMainVOById - 获取客户详情, id={}", id);

        CustomerMain customerMain = getById(id);
        if (customerMain == null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NOT_EXIST);
        }
        // 创建人/更新人 信息
        CustomerMainVO customerMainVO = BeanUtil.toBean(customerMain, CustomerMainVO.class);
        R<String> createdByNameR = userAccountServiceFeign.getName(customerMain.getCreatedBy());
        customerMainVO.setCreatedByName(createdByNameR.getData());
        R<String> updatedByNameR = userAccountServiceFeign.getName(customerMain.getUpdatedBy());
        customerMainVO.setUpdatedByName(updatedByNameR.getData());
        // 首要联系人
        Contact contact = contactService.getImportantContact(id, VenueBookingMoudleEnum.CUSTOMER.getCode());
        if (contact != null) {
            customerMainVO.setContactId(contact.getId());
            customerMainVO.setContactName(contact.getContactName());
            customerMainVO.setContactMobile(contact.getMobile());
        }
        // 重点关注
        UserCustomerStarQuery userCustomerStarPageQuery = new UserCustomerStarQuery();
        userCustomerStarPageQuery.setCustomerId(id);
        userCustomerStarPageQuery.setUserId(ContextUtil.getUserId());
        boolean isStarCustomer = userCustomerStarService.existUserCustomerStar(userCustomerStarPageQuery);
        customerMainVO.setIsStartCustomer(isStarCustomer);
        // 财务信息
        ContractManageVO contractManageVO = contractManageService.countContractManageByCustomerId(id);
        customerMainVO.setContractAmount(contractManageVO.getContractAmount());
        customerMainVO.setContractReturndAmount(contractManageVO.getContractReturndAmount());
        customerMainVO.setInvoicedAmount(contractManageVO.getInvoicedAmount());
        customerMainVO.setSureInvoicedAmount(contractManageVO.getSureInvoicedAmount());
        return customerMainVO;
    }

    @Override
    public CustomerMain getCustomerByContactId(Long contactId) {
        ContactRefQuery query = new ContactRefQuery();
        query.setContactId(contactId);
        query.setSubjectType(VenueBookingMoudleEnum.CUSTOMER.getCode());
        ContactRef contactRef = contactRefService.getContactRef(query);
        if (contactRef != null) {
            return getById(contactRef.getSubjectId());
        }
        return null;
    }

    @Override
    public CustomerStatisticsVO getCustomerStatistics(Long id) {
        log.info("getCustomerStatistics - 查询客户统计信息, id={}", id);

        CustomerStatisticsVO customerStatisticsVO = new CustomerStatisticsVO();
        customerStatisticsVO.setId(id);
        // 累计办展次数
        long exhibitionCount = exhibitionService.countExhibitionByCustomerId(id);
        customerStatisticsVO.setExhibitionCount(exhibitionCount);
        // 累计消费总额
        BigDecimal contractAmount = contractManageMapper.countContractAmountByCustomerId(id);
        customerStatisticsVO.setConsumeAmount(contractAmount);
        // 累计预定面积
        Double totalPriceArea = contractManageMapper.countPriceAreaByCustomerId(id);
        customerStatisticsVO.setTotalPriceArea(totalPriceArea);
        // 累计场地数量
        long spaceCount = contractManageMapper.countSpaceByCustomerId(id);
        customerStatisticsVO.setSpaceCount(spaceCount);
        // 联系人数量
        long contactCount = contactMapper.countContactByCustomerId(id);
        customerStatisticsVO.setContactCount(contactCount);
        // 商机数量
        long businessOpportunityCount = businessOpportunityService.countBusinessOpportunityByCustomerId(id);
        customerStatisticsVO.setBusinessOpportunityCount(businessOpportunityCount);
        // 跟进记录数量
        long followRecordCount = followRecordService.countFollowRecordByCustomerId(id);
        customerStatisticsVO.setFollowRecordCount(followRecordCount);
        // 归属记录数量
        long belongToCount = belongRecordService.countBelongRecordByCustomerId(id);
        customerStatisticsVO.setBelongToCount(belongToCount);
        return customerStatisticsVO;
    }

    @Override
    public CustomerMain getCustomerByName(String customerName) {
        CustomerMainDTO customerMainDTO = new CustomerMainDTO();
        customerMainDTO.setCustomerCnName(customerName);
        return getCustomer(customerMainDTO);
    }

    @Override
    public CustomerMain getCustomerByUscc(String uscc) {
        CustomerMainDTO customerMainDTO = new CustomerMainDTO();
        customerMainDTO.setUscc(uscc);
        return getCustomer(customerMainDTO);
    }

    @Override
    public CustomerMain getCustomer(CustomerMainDTO customerMainDTO) {
        QueryWrapper<CustomerMain> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .last("limit 1")
                .eq(StrUtil.isNotBlank(customerMainDTO.getCustomerCnName()), CustomerMain::getCustomerCnName, customerMainDTO.getCustomerCnName())
                .eq(StrUtil.isNotBlank(customerMainDTO.getUscc()), CustomerMain::getUscc, customerMainDTO.getUscc())
                .eq(CustomerMain::getIsDeleted, BusinessConstant.DELETE_NO);
        return getOne(queryWrapper);
    }

    @Override
    public List<ContractHistogramVO> countEveryYearContractAmountById(Long id) {
        log.info("countEveryYearContractAmountById - ID统计每年的成交量, id={}", id);

        return contractManageService.countEveryYearContractAmountByCustomerId(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveCustomerMain(CustomerMainContactSaveDTO saveDTO) {
        log.info("saveCustomerMain - 保存客户, saveDTO={}", saveDTO);
        if (StrUtil.isNotBlank(saveDTO.getCustomerCnName()) && getCustomerByName(saveDTO.getCustomerCnName()) != null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NAME_EXIST);
        }
        if (StrUtil.isNotBlank(saveDTO.getUscc()) && getCustomerByUscc(saveDTO.getUscc()) != null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_USCC_EXIST);
        }
        // 保存客户
        CustomerMain customerMain = BeanUtil.toBean(saveDTO, CustomerMain.class);
        save(customerMain);
        // 保存联系人
        ContactDTO contactSaveDTO = saveDTO.getContact();
        if (contactSaveDTO != null) {
            ContactRefDTO contactRefSaveDTO = new ContactRefDTO();
            contactRefSaveDTO.setSubjectId(customerMain.getId());
            contactRefSaveDTO.setSubjectType(VenueBookingMoudleEnum.CUSTOMER.getCode());
            contactRefSaveDTO.setImportant(true);
            contactSaveDTO.setContactRef(contactRefSaveDTO);
            contactService.saveContact(contactSaveDTO);
        }
        saveDTO.setId(customerMain.getId());
        return true;
    }

    @Override
    public Map<String, Object> saveForVenueBook(VenueBookAudit venueBookAudit) {
        log.info("saveForVenueBook - 场馆预定审核通过生成客户，联系人, venueBookAudit={}", venueBookAudit);
        CustomerMain customerMain = null;
        if (StrUtil.isNotBlank(venueBookAudit.getCustomerCnName())) {
            customerMain = getCustomerByName(venueBookAudit.getCustomerCnName());
        }
        if (customerMain == null && StrUtil.isNotBlank(venueBookAudit.getUscc())) {
            customerMain = getCustomerByUscc(venueBookAudit.getUscc());
        }
        if (customerMain != null) {
            // 保存联系人
            ContactDTO contractDTO = new ContactDTO();
            contractDTO.setContactName(venueBookAudit.getContactName());
            contractDTO.setMobile(venueBookAudit.getMobile());
            contractDTO.setRole(venueBookAudit.getContactRole());
            ContactRefDTO contactRefDTO = new ContactRefDTO();
            contactRefDTO.setSubjectId(customerMain.getId());
            contactRefDTO.setSubjectType(VenueBookingMoudleEnum.CUSTOMER.getCode());
            contactRefDTO.setImportant(false);
            contractDTO.setContactRef(contactRefDTO);
            contactService.saveContact(contractDTO);
            // 返回客户和联系人的信息
            Map<String, Object> map = new HashMap<>(16);
            map.put("customerMainId", customerMain.getId());
            map.put("customerMainName", customerMain.getCustomerCnName());
            map.put("isNewCustomerMain", false);
            map.put("contactId", contractDTO.getId());
            map.put("contactName", contractDTO.getContactName());
            return map;
        }
        // 生成客户
        CustomerMainContactSaveDTO customerMainContractDTO = new CustomerMainContactSaveDTO();
        customerMainContractDTO.setCustomerCnName(venueBookAudit.getCustomerCnName());
        customerMainContractDTO.setUscc(venueBookAudit.getUscc());
        // 生成客户联系人
        ContactDTO contractDTO = new ContactDTO();
        contractDTO.setContactName(venueBookAudit.getContactName());
        contractDTO.setMobile(venueBookAudit.getMobile());
        contractDTO.setRole(venueBookAudit.getContactRole());
        customerMainContractDTO.setContact(contractDTO);
        // 保存客户与联系人
        saveCustomerMain(customerMainContractDTO);
        // 返回客户和联系人的信息
        Map<String, Object> map = new HashMap<>(16);
        map.put("customerMainId", customerMainContractDTO.getId());
        map.put("customerMainName", customerMainContractDTO.getCustomerCnName());
        map.put("isNewCustomerMain", true);
        map.put("contactId", contractDTO.getId());
        map.put("contactName", contractDTO.getContactName());
        return map;
    }

    @Override
    protected R<Boolean> handlerUpdateById(CustomerMain model) {
        CustomerMain customerByName = getCustomerByName(model.getCustomerCnName());
        if (customerByName != null && !model.getId().equals(customerByName.getId())) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NAME_EXIST);
        }
        CustomerMain customerByUscc = getCustomerByUscc(model.getUscc());
        if (customerByUscc != null && !model.getId().equals(customerByUscc.getId())) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_USCC_EXIST);
        }
        return R.successDef();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePublic(CustomerMainPublicDTO publicDTO) {
        List<CustomerMainDTO> updateList = publicDTO.getUpdateList();
        List<Long> ids = updateList
                .stream()
                .map(CustomerMainDTO::getId)
                .collect(Collectors.toList());
        // 客户移入公海，关联数据如何处理存在疑问，先去掉校验
//        if (saleClueService.existSaleClueByCustomerId(ids)) {
//            throw BizException.wrap(VenueBookingExceptionCode.CLUE_EXIST_CAN_NOT_DELETE);
//        }
//        if (businessOpportunityService.existBusinessOpportunityByCustomerIds(ids)) {
//            throw BizException.wrap(VenueBookingExceptionCode.BUS_EXIST_CAN_NOT_DELETE);
//        }
//        if (exhibitionService.existExhibitionByCustomerIds(ids)) {
//            throw BizException.wrap(VenueBookingExceptionCode.EX_EXIST_CAN_NOT_DELETE);
//        }
//        if (contractManageService.existContractManageByCustomerIds(ids)) {
//            throw BizException.wrap(VenueBookingExceptionCode.CONTRACT_EXIST_CAN_NOT_DELETE);
//        }
        for (CustomerMainDTO updateDTO : updateList) {
            // 更新客户
            updateDTO.setLastBelongTo(updateDTO.getBelongTo());
            updateDTO.setLastBelongToName(updateDTO.getBelongToName());
            updateDTO.setLastOrgCode(updateDTO.getOrgCode());
            updateDTO.setLastOrgName(updateDTO.getOrgName());
            updateDTO.setBelongTo(null);
            updateDTO.setBelongToName(null);
            updateDTO.setOrgCode(null);
            updateDTO.setOrgName(null);
            updateDTO.setState(CustomerStateEnum.PUBLIC.getCode());
            updateState(updateDTO);
            // 保存归属记录
            CustomerMainAssignDTO assignDTO = new CustomerMainAssignDTO();
            assignDTO.setId(updateDTO.getId());
            assignDTO.setLastBelongTo(updateDTO.getLastBelongTo());
            assignDTO.setLastBelongToName(updateDTO.getLastBelongToName());
            assignDTO.setRemark(publicDTO.getRemark());
            assignDTO.setBusinessType(VenueBookingMoudleEnum.CUSTOMER.getCode());
            assignDTO.setOperateType(BelongRecordOperateTypeEnum.MOVE_IN_PUBLIC);
            belongRecordService.saveBelongRecord(assignDTO);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBelongTo(CustomerMainAssignDTO assignDTO) {

        CustomerMain customerMain = getById(assignDTO.getId());
        if (customerMain == null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NOT_EXIST);
        }
        assignDTO.setLastBelongTo(customerMain.getBelongTo());
        assignDTO.setLastBelongToName(customerMain.getBelongToName());
        assignDTO.setLastOrgCode(customerMain.getOrgCode());
        assignDTO.setLastOrgName(customerMain.getOrgName());
        assignDTO.setBusinessType(VenueBookingMoudleEnum.CUSTOMER.getCode());
        // 更新客户
        CustomerMainDTO updateDTO = new CustomerMainDTO();
        updateDTO.setId(assignDTO.getId());
        updateDTO.setBelongTo(assignDTO.getBelongTo());
        updateDTO.setBelongToName(assignDTO.getBelongToName());
        updateDTO.setOrgCode(assignDTO.getOrgCode());
        updateDTO.setOrgName(assignDTO.getOrgName());
        updateDTO.setLastBelongTo(assignDTO.getLastBelongTo());
        updateDTO.setLastBelongToName(assignDTO.getLastBelongToName());
        updateDTO.setLastOrgCode(assignDTO.getLastOrgCode());
        updateDTO.setLastOrgName(assignDTO.getLastOrgName());
        updateDTO.setState(CustomerStateEnum.NORMAL.getCode());
        updateState(updateDTO);
        // 保存归属记录
        return belongRecordService.saveBelongRecord(assignDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBelongTo(List<CustomerMainAssignDTO> list) {
        boolean result = true;
        for (CustomerMainAssignDTO assignDTO : list) {
            result = result & updateBelongTo(assignDTO);
        }
        return result;
    }

    @Override
    public boolean updateSilence(CustomerMainDTO updateDTO) {
        // 更新客户
        updateDTO.setLastBelongTo(updateDTO.getBelongTo());
        updateDTO.setLastBelongToName(updateDTO.getBelongToName());
        updateDTO.setBelongTo(null);
        updateDTO.setBelongToName(null);
        updateDTO.setState(CustomerStateEnum.SILENCE.getCode());
        updateState(updateDTO);
        // 保存归属记录
        CustomerMainAssignDTO assignDTO = new CustomerMainAssignDTO();
        assignDTO.setId(updateDTO.getId());
        assignDTO.setLastBelongTo(updateDTO.getLastBelongTo());
        assignDTO.setLastBelongToName(updateDTO.getLastBelongToName());
        assignDTO.setBusinessType(VenueBookingMoudleEnum.CUSTOMER.getCode());
        assignDTO.setOperateType(BelongRecordOperateTypeEnum.MOVE_IN_SILENCE);
        return belongRecordService.saveBelongRecord(assignDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateState(CustomerMainDTO updateDTO) {
        // 更新状态
        UpdateWrapper<CustomerMain> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .lambda()
                .set(updateDTO.getState() != null, CustomerMain::getState, updateDTO.getState())
                .set(CustomerMain::getLastBelongTo, updateDTO.getLastBelongTo())
                .set(CustomerMain::getLastBelongToName, updateDTO.getLastBelongToName())
                .set(CustomerMain::getLastOrgCode, updateDTO.getLastOrgCode())
                .set(CustomerMain::getLastOrgName, updateDTO.getLastOrgName())
                .set(CustomerMain::getBelongTo, updateDTO.getBelongTo())
                .set(CustomerMain::getBelongToName, updateDTO.getBelongToName())
                .set(CustomerMain::getOrgCode, updateDTO.getOrgCode())
                .set(CustomerMain::getOrgName, updateDTO.getOrgName())
                .eq(updateDTO.getId() != null, CustomerMain::getId, updateDTO.getId());
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFollow(CustomerMainDTO updateDTO) {
        UpdateWrapper<CustomerMain> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .lambda()
                .eq(updateDTO.getId() != null, CustomerMain::getId, updateDTO.getId())
                .set(StrUtil.isNotBlank(updateDTO.getCustomerStatus()),
                        CustomerMain::getCustomerStatus, updateDTO.getCustomerStatus())
                .set(updateDTO.getLastFollowDate() != null,
                        CustomerMain::getLastFollowDate, updateDTO.getLastFollowDate())
                .set(updateDTO.getNextFollowDate() != null,
                        CustomerMain::getNextFollowDate, updateDTO.getNextFollowDate())
        ;
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFollow(FollowRecordPlanSaveDTO saveDTO) {
        CustomerMain customerMain = getById(saveDTO.getCustomerId());
        if (customerMain == null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NOT_EXIST);
        }
        LocalDateTime lastFollowDate = FollowRecordService.getLastFollowDate(saveDTO.getFollowDateTime(), customerMain.getLastFollowDate());
        LocalDateTime nextFollowDate = customerMain.getNextFollowDate();
        if (saveDTO.getFollowPlanSaveDTO() != null) {
            nextFollowDate = FollowPlanService.getNextFollowDate(saveDTO.getFollowPlanSaveDTO().getPlanFollowDate(), customerMain.getNextFollowDate());
        }
        // 计算最后跟进时间
        CustomerMainDTO updateDTO = new CustomerMainDTO();
        updateDTO.setId(saveDTO.getCustomerId());
        updateDTO.setCustomerStatus(saveDTO.getCustomerStatus());
        updateDTO.setLastFollowDate(lastFollowDate);
        if (saveDTO.getFollowPlanSaveDTO() != null) {
            updateDTO.setNextFollowDate(nextFollowDate);
        }
        return updateFollow(updateDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStartCustomerMain(CustomerMainStartDTO startDTO) {
        // 关注
        if (startDTO.getStar()) {
            UserCustomerStarQuery query = BeanUtil.toBean(startDTO, UserCustomerStarQuery.class);
            if (userCustomerStarService.existUserCustomerStar(query)) {
                throw BizException.wrap(VenueBookingExceptionCode.CUS_USER_START_EXIST);
            }
            UserCustomerStar star = BeanUtil.toBean(startDTO, UserCustomerStar.class);
            return userCustomerStarService.save(star);
        }
        // 取关
        UserCustomerStarDTO updateDTO = BeanUtil.toBean(startDTO, UserCustomerStarDTO.class);
        return userCustomerStarService.removeByUserIdAndCustomerId(updateDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCrmSync(CustomerMainDTO customerMainDTO) {
        log.info("updateCmsSync - 更新客户cms同步状态, customerMainDTO={}", customerMainDTO);
        CustomerMain customerMain = getById(customerMainDTO.getId());
        if (customerMain == null) {
            throw BizException.wrap(VenueBookingExceptionCode.CUS_NOT_EXIST);
        }
        customerMain.setCmsSync(customerMainDTO.getCmsSync());
        return updateById(customerMain);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCrmHasSync(List<Long> ids) {
        List<CustomerMain> list = listByIds(ids);
        if (list == null || list.isEmpty()) {
            return false;
        }
        for (CustomerMain customerMain: list) {
            customerMain.setCmsSync(BusinessConstant.YES);
            updateById(customerMain);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeCustomerMainByIds(List<Long> ids) {
        log.info("removeCustomerMainByIds - 删除客户, ids={}", ids);

        if (saleClueService.existSaleClueByCustomerId(ids)) {
            throw BizException.wrap(VenueBookingExceptionCode.CLUE_EXIST_CAN_NOT_DELETE);
        }
        if (businessOpportunityService.existBusinessOpportunityByCustomerIds(ids)) {
            throw BizException.wrap(VenueBookingExceptionCode.BUS_EXIST_CAN_NOT_DELETE);
        }
        if (exhibitionService.existExhibitionByCustomerIds(ids)) {
            throw BizException.wrap(VenueBookingExceptionCode.EX_EXIST_CAN_NOT_DELETE);
        }
        if (contractManageService.existContractManageByCustomerIds(ids)) {
            throw BizException.wrap(VenueBookingExceptionCode.CONTRACT_EXIST_CAN_NOT_DELETE);
        }
        // 移除客户
        List<CustomerMain> deleteCustomerMainList = listByIds(ids);
        boolean remove = removeByIdsOfLogic(deleteCustomerMainList);
        if (remove) {
            // 移除联系人关联
            ContactRefDTO updateDTO = new ContactRefDTO();
            updateDTO.setSubjectIds(ids);
            updateDTO.setSubjectType(VenueBookingMoudleEnum.CUSTOMER.getCode());
            return contactRefService.removeContactRef(updateDTO);
        }
        return true;
    }

    public void handlerQueryParams(PageParams<CustomerMainQuery> params) {
        if (StrUtil.isBlank(params.getSort()) || StrUtil.isBlank(params.getOrder())) {
            params.setSort("createTime");
            params.setOrder("descending");
        }
    }

    private QueryWrapper<CustomerMain> createCustomerMainQueryWrapper(CustomerMainQuery query) {
        QueryWrapper<CustomerMain> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .and(StrUtil.isNotBlank(query.getKeyword()), param ->
                        param.like("cm.customer_cn_name", query.getKeyword())
                                .or()
                                .like("con.contact_name", query.getKeyword())
                                .or()
                                .like("con.mobile", query.getKeyword()))
                .eq(StrUtil.isNotBlank(query.getCustomerStatus()),
                        "cm.customer_status", query.getCustomerStatus())
                .eq(StrUtil.isNotBlank(query.getCustomerType()),
                        "cm.customer_type", query.getCustomerType())
                .eq(StrUtil.isNotBlank(query.getCustomerLevel()),
                        "cm.customer_level", query.getCustomerLevel())
                .between(StrUtil.isNotBlank(query.getLastFollowBeginDate())
                                && StrUtil.isNotBlank(query.getLastFollowEndDate()),
                        "cm.last_follow_date", query.getLastFollowBeginDate(), query.getLastFollowEndDate())
                .eq(StrUtil.isNotBlank(query.getCustomerIndustry()),
                        "cm.customer_industry", query.getCustomerIndustry())
                .eq(StrUtil.isNotBlank(query.getCustomerSource()),
                        "cm.customer_source", query.getCustomerSource())
                .eq(query.getBelongTo() != null, "cm.belong_to", query.getBelongTo())
                .like(StrUtil.isNotBlank(query.getBelongToName()), "cm.belong_to_name", query.getBelongToName())
                .eq(query.getCreatedBy() != null, "cm.created_by", query.getCreatedBy())
                .eq(query.getState() != null, "cm.state", query.getState())
                .eq(query.getStarUserId() != null, "ucs.user_id", query.getStarUserId())
                .eq("cm.is_deleted", BusinessConstant.DELETE_NO)
                .groupBy("cm.id")
        ;
        return queryWrapper;
    }
}
